#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<time.h>
#include"cJSON.h"

#define LL_SERVER_PORT 12344
#define SL_SERVER_PORT 12345
#define BUF_SIZE 4096
#define QUEUE_SIZE 10
#define SL_IP "127.0.0.1"

int main(int argc, char* argv[])
{
	//create socket and listen
	int s, b,l, sa, on = 1;
	char buf[BUF_SIZE];
	char resbuf[BUF_SIZE];
	char name[256];
	char pwd[256];
	struct  sockaddr_in channel;

	memset(&channel, 0, sizeof(channel));
	channel.sin_family = AF_INET;
	channel.sin_addr.s_addr = htonl(INADDR_ANY);
	channel.sin_port = htons(LL_SERVER_PORT);
	
	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(s < 0 )
		printf("login server create socket fail!");
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));

	b = bind(s, (struct sockaddr*)&channel, sizeof(channel));
	if(b < 0 )
		printf("login server bind fail!");

	l = listen(s, QUEUE_SIZE);
	if(l < 0 )
		printf("login server listen fail!");

	while(1){		
		sa = accept(s, 0, 0);
		if(sa < 0 )
			printf("login server accept fail!");
		read(sa, buf, BUF_SIZE);
		printf("login server get the massage from client:%s\n",buf);
		
		//get username and pwd
		int i;
		for(i = 2; i < BUF_SIZE; i++)
			if(buf[i] != '-')
				name[i-2] = buf[i];
			else break;
		name[i-2] = '\0';
		int j = ++i;
		for(; i < BUF_SIZE; i++)
			if(buf[i] != '\0')
				pwd[i-j] = buf[i];
			else break;
		pwd[i-2] = '\0';
		printf("get the username :%s\n",name);
		printf("get the password:%s\n",pwd);			
			
		//create socket for storage level
		int sl_c, sl_s, sl_s1;
		char sl_buf[BUF_SIZE];
		char sl_resbuf[BUF_SIZE];
		struct hostent* sl_h;
		struct sockaddr_in sl_channel;

		sl_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
		if(sl_s < 0 )
			printf("login server create socket fail!\n");
	
		memset(&sl_channel, 0, sizeof(sl_channel));
		sl_channel.sin_family = AF_INET;
		sl_channel.sin_port = htons(SL_SERVER_PORT);
		inet_pton(AF_INET, SL_IP, &channel.sin_addr);

		sl_c = connect(sl_s, (struct sockaddr *)&sl_channel, sizeof(sl_channel));
		if(sl_c < 0 )
			printf("login server connect fail\n");

		//logic 
		char QUERY_BUF[2048] = {0};
		char* select_query = "select * from user where UserName = \"";
		if(buf[0] == '1')//sign up
		{
			strcat(QUERY_BUF, select_query);
			strcat(QUERY_BUF, name);
			strcat(QUERY_BUF, "\"");
			fprintf(stdout,"select_query:\n%s\n",QUERY_BUF);
			write(sl_s, QUERY_BUF, 2048);
			while(1){
				int bytes = read(sl_s, sl_resbuf, BUF_SIZE);
				if(bytes <= 0)
					break;
			}
			close(sl_s);
			fprintf(stdout,"sign up select receive from storage server:\n%s\n",sl_resbuf);
			bool already_exist = false;
			cJSON *root = cJSON_Parse(sl_resbuf);
			if(cJSON_GetObjectItem(root, "result")->valueint > 0)
				already_exist = true;
			cJSON_Delete(root);
			if(already_exist){//exist the username
				cJSON *res_root = cJSON_CreateObject();
				cJSON_AddNumberToObject(res_root, "type", -1);
				cJSON_AddStringToObject(res_root, "msg", "already exist the username");
				char* out=cJSON_Print(res_root);	
				cJSON_Delete(res_root);		
				strcat(resbuf,out);
				free(out);
			}
			else{//sign up the username
				memset(QUERY_BUF, 0, 2048);
				time_t timer = time(NULL);
				char str_time[32] = {0};
				sprintf(str_time, "%d", timer);
				char* insert_query = "insert into user (UserName,UserPassWord,Token) values (\"";
				strcat(QUERY_BUF, insert_query);
				strcat(QUERY_BUF, name);
				strcat(QUERY_BUF, "\",\"");
				strcat(QUERY_BUF, pwd);
				strcat(QUERY_BUF, "\",\"");	
				strcat(QUERY_BUF, str_time);
				strcat(QUERY_BUF,"\")");
				fprintf(stdout,"insert_query:\n%s\n",QUERY_BUF);
				sl_s1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
				if(sl_s1 < 0 )
					printf("login server create socket1 fail!\n");
				sl_c = connect(sl_s1, (struct sockaddr *)&sl_channel, sizeof(sl_channel));
				if(sl_c < 0 ){
					perror("connetc error: ");
					printf("login server connect fail\n");
				}
				write(sl_s1, QUERY_BUF, 2048);
				while(1){
					int bytes = read(sl_s1, sl_resbuf, BUF_SIZE);
					if(bytes <= 0)
						break;
				}
				close(sl_s1);
				cJSON *ins_res_root = cJSON_Parse(sl_resbuf);
				cJSON *res_root = cJSON_CreateObject();
				if(cJSON_GetObjectItem(ins_res_root, "result")->valueint == 0)
				{//insert success
					cJSON_AddNumberToObject(res_root, "type", 0);
				}
				else
				{//insert fail
					cJSON_AddNumberToObject(res_root, "type", -1);
					cJSON_AddStringToObject(res_root, "msg", cJSON_GetObjectItem(ins_res_root, "msg")->valuestring);
				}
				char* out=cJSON_Print(res_root);	
				cJSON_Delete(res_root);		
				strcat(resbuf,out);
				free(out);
				fprintf(stdout,"sign up insert receive from storage server:\n%s\n",sl_resbuf);
			}
			
		}
		else if(buf[0] == '2')//login
		{
			strcat(QUERY_BUF, select_query);
			strcat(QUERY_BUF, name);
			strcat(QUERY_BUF, "\" and UserPassword = \"");
			strcat(QUERY_BUF, pwd);
			strcat(QUERY_BUF, "\"");
			fprintf(stdout,"select_query:\n%s\n",QUERY_BUF);
			write(sl_s, QUERY_BUF, 2048);
			while(1){
				int bytes = read(sl_s, sl_resbuf, BUF_SIZE);
				if(bytes <= 0)
					break;
			}
			close(sl_s);
			fprintf(stdout,"login select receive from storage server:\n%s\n",sl_resbuf);
			cJSON *root = cJSON_Parse(sl_resbuf);
			cJSON *res_root = cJSON_CreateObject();
			if(cJSON_GetObjectItem(root, "result")->valueint == 0){
				cJSON_AddNumberToObject(res_root, "type", -1);
				cJSON_AddStringToObject(res_root, "msg", "wrong username or password");
			}
			else{
				cJSON_AddNumberToObject(res_root, "type", 0);
				cJSON *info = cJSON_GetObjectItem(root, "info");
				cJSON *node = cJSON_GetArrayItem(info, 0);
				cJSON_AddStringToObject(res_root, "token", cJSON_GetObjectItem(node, "Token")->valuestring);
			}
			char* out=cJSON_Print(res_root);	
			cJSON_Delete(res_root);		
			strcat(resbuf,out);
			free(out);
		}
		else
			printf("error msg tpye\n");

		write(sa, resbuf, BUF_SIZE);
		close(sa);
		memset(resbuf, 0, BUF_SIZE);
	}
	return 0;
}
	
